package pl.diagnoser.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import pl.diagnoser.client.dto.DiagnoserResultsDTO;
import pl.diagnoser.client.tools.DataGetterService;
import pl.diagnoser.client.tools.DataGetterServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Slider;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.ValueChangedEvent;
import com.smartgwt.client.widgets.events.ValueChangedHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class SystemLearning extends Canvas {
	
	private DataGetterServiceAsync dataGetterAsc = GWT.create(DataGetterService.class);
	private VLayout mainLayout;
	private HLayout modeLayout;
	private HLayout sliderLayout;
	private SelectItem modeSelector;
	private Label modeHint;
	private DynamicForm form;
	private LinkedHashMap<String, String> modeValues;
	
	private Label sliderHintPu;
	private Label sliderHintPt;
	private Slider slider;
	
	private Button startLearnButton;
	
	private ListGrid implicationList;
	private ListGridField implication;
	private ListGridField confidence;
	private ListGridField baseConfidence;
	
	private Button saveButton;
	
	private static String MODE_PODSTAWOWY = "algorytm douczający korzysta z oryginalnie przypisanych symptomów";
	private static String MODE_ZASTEPOWANIE = "algorytm douczający zastępuje oryginalne symptomy ich zgeneralizowanymi odpowiednikami";
	private static String MODE_DODAWANIE = "algorytm douczający uzupełnia oryginalne symptomy o ich generalizacje";
	private static String MODE_PODOBIENSTWO = "algorytm douczający uzupełnia oryginalne sypmtomy o ich podobieństwa";
	private static String SLIDER_PU = "Przykłady do uczenia: ";
	private static String SLIDER_PT = "Przykłady testowe: ";
	
	public SystemLearning() {
		super();
		this.setHeight100();
		this.setWidth100();
		
		
		mainLayout = new VLayout();
		mainLayout.setWidth100();
		mainLayout.setHeight100();
		mainLayout.setMargin(5);
		mainLayout.setMembersMargin(3);
		
		modeLayout = new HLayout();
		modeLayout.setWidth100();
		modeLayout.setHeight(30);
		modeLayout.setMembersMargin(10);
		
		modeHint = new Label();
		modeHint.setContents(MODE_PODSTAWOWY);
		modeHint.setWidth100();
		modeHint.setHeight(18);
		
		modeValues = new LinkedHashMap<String, String>();
		initModes();
		
		modeSelector = new SelectItem();
		modeSelector.setName("modeSelector");
		modeSelector.setDefaultToFirstOption(true);
		modeSelector.setTitle("Tryb");
		modeSelector.setValueMap(modeValues);
		modeSelector.setHeight(18);
		modeSelector.setWidth(180);
		modeSelector.addChangedHandler(new ChangedHandler() {
			public void onChanged(ChangedEvent event) {
				switch(new Integer((String)event.getValue())) {
					case 0: modeHint.setContents(MODE_PODSTAWOWY);
							break;
					case 1: modeHint.setContents(MODE_ZASTEPOWANIE);
							break;
					case 2: modeHint.setContents(MODE_DODAWANIE);
							break;
					case 3: modeHint.setContents(MODE_PODOBIENSTWO);
							break;
				}
			}
		});
		
		form = new DynamicForm();
		form.setFields(modeSelector);
		form.setWidth(230);
		
		modeLayout.addMember(form);
		modeLayout.addMember(modeHint);
		
		sliderLayout = new HLayout();
		sliderLayout.setWidth100();
		sliderLayout.setHeight(50);
		sliderLayout.setMembersMargin(20);
		
		sliderHintPu = new Label();
		sliderHintPu.setHeight100();
		sliderHintPu.setAlign(Alignment.CENTER);
		sliderHintPu.setWidth(150);
		
		sliderHintPt = new Label();
		sliderHintPt.setHeight100();
		sliderHintPt.setAlign(Alignment.CENTER);
		sliderHintPt.setWidth(150);
		
		slider = new Slider();
		slider.setTitle("Podział przykładów: ");
		slider.setVertical(false);
		slider.setMinValue(0);
		slider.setMaxValue(100);
		slider.setNumValues(11);
		slider.setTrackWidth(3);
		slider.setLabelWidth(100);
		slider.setLabelHeight(6);
		slider.setLength(175);
		slider.setValue(0);
		slider.setWidth(300);
		slider.addValueChangedHandler(new ValueChangedHandler() {
			public void onValueChanged(ValueChangedEvent event) {
				sliderHintPu.setContents(getSliderHintPu());
				sliderHintPt.setContents(getSliderHintPt());
			}
		});
		sliderHintPu.setContents(getSliderHintPu());
		sliderHintPt.setContents(getSliderHintPt());
		
		sliderLayout.addMember(slider);
		sliderLayout.addMember(sliderHintPu);
		sliderLayout.addMember(sliderHintPt);
		
		startLearnButton = new Button();
		startLearnButton.setTitle("Uruchom douczanie");
		startLearnButton.setWidth(150);
		startLearnButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				runLearining(Integer.valueOf((String) modeSelector.getValueAsString()), (double)slider.getValue()/100);
			}
		});
		
		implication = new ListGridField();
		implication.setName("implication");
		implication.setTitle("Implikacja");
		implication.setWidth(966);
		
		confidence = new ListGridField();
		confidence.setName("confidence");
		confidence.setTitle("Pewność");
		confidence.setWidth(100);
		confidence.setType(ListGridFieldType.FLOAT);
		
		baseConfidence = new ListGridField();
		baseConfidence.setName("baseConfidence");
		baseConfidence.setTitle("Pewność bazowa");
		baseConfidence.setType(ListGridFieldType.FLOAT);
		baseConfidence.setWidth(110);
		
		implicationList = new ListGrid();
		implicationList.setWidth100();
		implicationList.setHeight(235);
		implicationList.setShowAllRecords(true);
		implicationList.setSelectionType(SelectionStyle.SIMPLE);
		implicationList.setSelectionAppearance(SelectionAppearance.CHECKBOX);
		implicationList.setAutoFetchData(false);
		implicationList.setFields(implication, confidence, baseConfidence);
		
		saveButton = new Button();
		saveButton.setTitle("Zapisz zaznaczone");
		saveButton.setWidth(150);
		saveButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				List<ListGridRecord> selectedRecords = Arrays.asList(implicationList.getSelectedRecords());
				ArrayList<String> implications = new ArrayList<String>();
				for(ListGridRecord record : selectedRecords) {
					implications.add(record.getAttributeAsString("implication"));
				}
				saveImplication(implications, implicationList);
			}
		});
		
		mainLayout.addMember(modeLayout);
		mainLayout.addMember(sliderLayout);
		mainLayout.addMember(startLearnButton);
		mainLayout.addMember(implicationList);
		mainLayout.addMember(saveButton);
		
		this.addChild(mainLayout);
		this.draw();
		
	}
	/*
	public void fire() {
		this.clear();
		
		mainLayout = new VLayout();
		mainLayout.setWidth100();
		mainLayout.setHeight100();
		mainLayout.setMargin(5);
		mainLayout.setMembersMargin(3);
		
		modeLayout = new HLayout();
		modeLayout.setWidth100();
		modeLayout.setHeight(30);
		modeLayout.setMembersMargin(10);
		
		modeHint = new Label();
		modeHint.setContents(MODE_PODSTAWOWY);
		modeHint.setWidth100();
		modeHint.setHeight(18);
		
		modeValues = new LinkedHashMap<String, String>();
		initModes();
		
		modeSelector = new SelectItem();
		modeSelector.setName("modeSelector");
		modeSelector.setDefaultToFirstOption(true);
		modeSelector.setTitle("Tryb");
		modeSelector.setValueMap(modeValues);
		modeSelector.setHeight(18);
		modeSelector.setWidth(180);
		modeSelector.addChangedHandler(new ChangedHandler() {
			public void onChanged(ChangedEvent event) {
				switch(new Integer((String)event.getValue())) {
					case 0: modeHint.setContents(MODE_PODSTAWOWY);
							break;
					case 1: modeHint.setContents(MODE_ZASTEPOWANIE);
							break;
					case 2: modeHint.setContents(MODE_DODAWANIE);
							break;
					case 3: modeHint.setContents(MODE_PODOBIENSTWO);
							break;
				}
			}
		});
		
		form = new DynamicForm();
		form.setFields(modeSelector);
		form.setWidth(230);
		
		modeLayout.addMember(form);
		modeLayout.addMember(modeHint);
		
		sliderLayout = new HLayout();
		sliderLayout.setWidth100();
		sliderLayout.setHeight(50);
		sliderLayout.setMembersMargin(20);
		
		sliderHintPu = new Label();
		sliderHintPu.setHeight100();
		sliderHintPu.setAlign(Alignment.CENTER);
		sliderHintPu.setWidth(150);
		
		sliderHintPt = new Label();
		sliderHintPt.setHeight100();
		sliderHintPt.setAlign(Alignment.CENTER);
		sliderHintPt.setWidth(150);
		
		slider = new Slider();
		slider.setTitle("Podział przykładów: ");
		slider.setVertical(false);
		slider.setMinValue(0);
		slider.setMaxValue(100);
		slider.setNumValues(11);
		slider.setTrackWidth(3);
		slider.setLabelWidth(100);
		slider.setLabelHeight(6);
		slider.setLength(175);
		slider.setValue(0);
		slider.setWidth(300);
		slider.addValueChangedHandler(new ValueChangedHandler() {
			public void onValueChanged(ValueChangedEvent event) {
				sliderHintPu.setContents(getSliderHintPu());
				sliderHintPt.setContents(getSliderHintPt());
			}
		});
		sliderHintPu.setContents(getSliderHintPu());
		sliderHintPt.setContents(getSliderHintPt());
		
		sliderLayout.addMember(slider);
		sliderLayout.addMember(sliderHintPu);
		sliderLayout.addMember(sliderHintPt);
		
		startLearnButton = new Button();
		startLearnButton.setTitle("Uruchom douczanie");
		startLearnButton.setWidth(150);
		startLearnButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				runLearining(Integer.valueOf((String) modeSelector.getValueAsString()), (double)slider.getValue()/100);
			}
		});
		
		implication = new ListGridField();
		implication.setName("implication");
		implication.setTitle("Implikacja");
		implication.setWidth(966);
		
		confidence = new ListGridField();
		confidence.setName("confidence");
		confidence.setTitle("Pewność");
		confidence.setWidth(100);
		confidence.setType(ListGridFieldType.FLOAT);
		
		baseConfidence = new ListGridField();
		baseConfidence.setName("baseConfidence");
		baseConfidence.setTitle("Pewność bazowa");
		baseConfidence.setType(ListGridFieldType.FLOAT);
		baseConfidence.setWidth(110);
		
		implicationList = new ListGrid();
		implicationList.setWidth100();
		implicationList.setHeight(235);
		implicationList.setShowAllRecords(true);
		implicationList.setSelectionType(SelectionStyle.SIMPLE);
		implicationList.setSelectionAppearance(SelectionAppearance.CHECKBOX);
		implicationList.setAutoFetchData(false);
		implicationList.setFields(implication, confidence, baseConfidence);
		
		saveButton = new Button();
		saveButton.setTitle("Zapisz zaznaczone");
		saveButton.setWidth(150);
		saveButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				List<ListGridRecord> selectedRecords = Arrays.asList(implicationList.getSelectedRecords());
				ArrayList<String> implications = new ArrayList<String>();
				for(ListGridRecord record : selectedRecords) {
					implications.add(record.getAttributeAsString("implication"));
				}
				saveImplication(implications, implicationList);
			}
		});
		
		mainLayout.addMember(modeLayout);
		mainLayout.addMember(sliderLayout);
		mainLayout.addMember(startLearnButton);
		mainLayout.addMember(implicationList);
		mainLayout.addMember(saveButton);
		
		this.addChild(mainLayout);
		this.draw();
	}
	*/
	private void initModes() {
		modeValues.put("0", "podstawowy");
		modeValues.put("1", "uogólnianie z zastępowaniem");
		modeValues.put("2", "uogólnianie z dodawaniem");
		modeValues.put("3", "podobieństwo");
	}
	
	private String getSliderHintPu() {
		return SLIDER_PU + slider.getValue() + "%";
	}
	
	private String getSliderHintPt() {
		return SLIDER_PT + (float)(100-slider.getValue()) + "%";
	}
	
	private void runLearining(Integer mode, Double slider) {
		if (dataGetterAsc == null) {
			dataGetterAsc = GWT.create(DataGetterService.class);
		}
		
		AsyncCallback<List<DiagnoserResultsDTO>> callback = new AsyncCallback<List<DiagnoserResultsDTO>>() {
			public void onFailure(Throwable caught) {
				System.out.println(caught.getMessage());
			}

			public void onSuccess(List<DiagnoserResultsDTO> result) {
				DiagnoserResultsData.getInstance(result, implicationList).setRecords();
			}
		};
		
		dataGetterAsc.getLearnResult(mode, slider, callback);
	}
	
	private void saveImplication(List<String> implications, final ListGrid listGrid) {
		if (dataGetterAsc == null) {
			dataGetterAsc = GWT.create(DataGetterService.class);
		}
		
		AsyncCallback<String> callback = new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				System.out.println(caught.getMessage());
			}

			public void onSuccess(String result) {
				if(!result.equals((String)"OK"))
						SC.say("Błąd w trakie zapisu: " + result);
				else {
					listGrid.removeSelectedData();
				}
			}
		};
		
		dataGetterAsc.saveImplication(implications, callback);
	}
}

class DiagnoserResultsRecord extends ListGridRecord {
	
	DiagnoserResultsRecord() {}
	DiagnoserResultsRecord(String implication, Double confidence, Double baseConfidence) {
		setImplication(implication);
		setConfidence(confidence);
		setBaseConfidence(baseConfidence);
	}
	
	public void setImplication(String implication) {
		setAttribute("implication", implication);
	}
	
	public String getImplication() {
		return getAttributeAsString("implication");
	}
	
	public void setConfidence(Double confidence) {
		setAttribute("confidence", confidence);
	}
	
	public String getConfidence() {
		return getAttributeAsString("confidence");
	}
	
	public void setBaseConfidence(Double baseConfidence) {
		setAttribute("baseConfidence", baseConfidence);
	}
	
	public String getBaseConfidence() {
		return getAttributeAsString("baseConfidence");
	}
	
	public String getFieldValue(String field) {
		return getAttributeAsString(field);
	}
}

class DiagnoserResultsData {
	
	static DiagnoserResultsData instance = null;
	static List<DiagnoserResultsDTO> results;
	static ListGrid implicationList;
	
	public static DiagnoserResultsData getInstance(List<DiagnoserResultsDTO> newResults, ListGrid list) {
		if(instance == null) {
			results = newResults;
			implicationList = list;
			return new DiagnoserResultsData();
		}
		return instance;
	}
	
	public void setRecords() {
		ArrayList<DiagnoserResultsRecord> records = new ArrayList<DiagnoserResultsRecord>();
		for(DiagnoserResultsDTO result :results ) {
			records.add(new DiagnoserResultsRecord(result.getImplication(),
					result.getConfidence(), 
					result.getOldConfidence()));
		}
		
		implicationList.setData(records.toArray(new DiagnoserResultsRecord[records.size()]));
	}
}
